Next.js で Airtable を簡易データベースとして使ってみるよ
どうも、ベルリンオフィスの小西です。
ここ最近Next.jsを触っているのですが、外部DBからデータを引っ張ってくるために Airtable を利用するケースを紹介したいと思います。
Airtableとは
Excel/Googleスプレッドシートライクにデータベースを構築できるクラウドベースのアプリケーションです。
操作感はスプレッドシートに似ていて直感的でかつ、プライマリーフィールドの設定、各カラムへのデータ型の指定、デフォルト値のセットなど、RDBMS的な機能も利用できます。
APIでデータの操作もできるので、モックの簡易DBとしてサクッと使えるのも便利です。APIドキュメントも、最近よく見るタイプの、ログインしたら自分の情報がインサートされている形で素敵です。
Airtableの準備
※前段階としてAirtableに登録し、プロジェクトを作成します。
sample
というテーブルを作り、
- slug
- Title
- Description
というカラムを作成します。
ちなみに、レコード(一行)ごとのユニークIDと作成日はAirtable側で作成/保存されています(自分で作ってもいいけど)。
レコード取得APIの返り値は下記のようになります。 id
はAirtable側で振っているユニークIDです。
{ "id": "recbqWeotvpmDZC5P", "fields": { "Title": "テスト記事1 タイトル", "Description": "テスト記事1 本文本文本文本文本文本文本文本文本文本文本文", "slug": "test-post-1" }, "createdTime": "2021-04-19T15:23:35.000Z" }
ちなみにslugをプライマリーキーに設定してますが、Airtable側にユニークチェック機能はないので、レコードを登録する際はアプリ側もしくは運用側でユニークチェックが必要になるのでお気をつけください。
Next.jsの準備
まずさくっとNext.jsアプリを立ち上げます。
※Node.js の v10.13以降をダウンロードしておいてください。
npm init next-app sample-airtable
cd sample-airtable
npm run dev
これで http://localhost:3000/
にアクセスしてNext.jsのスタートページが立ち上がっていたらOK。いったんアプリを終了します。
パッケージのインストール
npm install airtable
環境変数ファイルの設置
AIRTABLE_API_KEY=keyXXXXXXXX AIRTABLE_BASE_ID=appXXXXXXXX AIRTABLE_TABLE_NAME=sample
- APIキーは https://airtable.com/account から [Generate API Key] で生成できます。
- Base ID は各プロジェクトごとに発行されるので、 https://airtable.com/api からプロジェクトを選択し、次のページで [The ID of this base is appXXXXXXXX] という記載で確認できます。
Airtableクライアントを作成し、テーブルのデータを扱えるようにします。
const Airtable = require('airtable'); const base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY }).base( process.env.AIRTABLE_BASE_ID ); const table = base(process.env.AIRTABLE_TABLE_NAME); export { table };
次に、pagesディレクトリの配下に posts.js
を作成し、下記の記述をします。
import Head from 'next/head' import styles from '../styles/Home.module.css' import { table } from './api/airtable'; export default function Posts({ airtableRecords }) { return ( <div className={styles.container}> <Head> <title>posts from Airtable</title> </Head> <main className={styles.main}> <h1 className={styles.title}> Posts </h1> <div> { airtableRecords.map((record) => <div style={{margin: 10, padding: 10, border: "solid 1px gray"}} key={record.id}> <h2>{record.fields.Title}</h2> <p>{record.fields.Description}</p> </div> ) } </div> </main> </div> ) } export async function getStaticProps(context) { let airtableRecords = await table .select({ maxRecords: 10, sort: [ {field: 'slug', direction: 'asc'}, {field: 'Title', direction: 'desc'}, ], }) .firstPage(); airtableRecords = airtableRecords.map((record) => { return { id: record.id, fields: record.fields } }); return { props: { airtableRecords: airtableRecords, }, }; }
ざっくり posts.js 内容の説明
静的ページとしてビルドするため getStaticProps
の中で処理をしています。
select
はレコードの諸々のデータが入ったオブジェクトを返すメソッドですが、中でオプションを指定できます。上記の例ではMAXのレコード数とソートを指定していますが、下記の例のようにフィールドの値で絞り込みなども行えます。
.select({ //slugがtest-post-3のレコードを除外する filterByFormula: "NOT({slug} = 'test-post-3')" })
また firstPage
メソッドは返り値のページ数の指定です。Airtableはデフォルトで最大100件までのレコードを1ページとして返すのですが、今回はそれ以下の数なので firstPage
を指定しています。100を超える場合は eachPage
メソッドを使いましょう。
詳しくは https://airtable.com/api に載っています。
データが取得できたかの確認
以上の準備を終えた上で、再度 npm run dev
をして http://localhost:3000/posts
にアクセスすると、下記のように記事が生成されているのが確認できると思います。
以上、非常に簡単に外部データをNext.js上で表示できました。
今回はビルド時にAirtableのデータを引っ張ってきてループで書き出す処理をしただけですが、Auth0と組み合わせて簡単なユーザーデータベースなども作成できます。
また今回は使っていないslugカラムをベースに記事詳細ページも生成したりできますね。
セットアップ不要でエンドポイントのある簡易データベースを使えるという意味でAirtableはこれから重宝しそうです。